package com.ccb.sc.common.modules.setting.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ccb.sc.common.bind.annotation.Mapping;
import com.ccb.sc.common.modules.setting.entity.Settings;
import com.ccb.sc.common.modules.setting.mapper.SettingsMapper;
import com.ccb.sc.common.modules.setting.service.ISettingsService;
import com.ccb.sc.common.util.AESUtil;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/**
 * <p>
 * 系统设置表 服务实现类
 * </p>
 *
 * @author ken
 * @since 2020-09-21
 */
@Service
@CacheConfig(cacheNames = "sys:settings")
public class SettingsServiceImpl extends ServiceImpl<SettingsMapper, Settings> implements ISettingsService {

    private static final BeanUtilsBean BEAN_UTILS;

    static {
        BEAN_UTILS = BeanUtilsBean.getInstance();
    }

    @Override
    @CacheEvict(allEntries = true)
    public <T> void saveSettings(T t) {
        Field[] fields = t.getClass().getDeclaredFields();
        for (Field field : fields) {
            String value = field.getName();
            boolean aes = false;
            boolean annotationPresent = field.isAnnotationPresent(Mapping.class);
            if (annotationPresent) {
                Mapping mapping = field.getAnnotation(Mapping.class);
                value = mapping.value();
                aes = mapping.aes();
            }
            String description = "";
            boolean apiPresent = field.isAnnotationPresent(ApiModelProperty.class);
            if (apiPresent) {
                ApiModelProperty apiModelProperty = field.getAnnotation(ApiModelProperty.class);
                description = apiModelProperty.value();
            }

            Settings setting = new Settings();
            setting.setId(StringUtils.isEmpty(value) ? field.getName() : value);
            try {
                String result = BEAN_UTILS.getProperty(t, field.getName());
                setting.setValue(aes ? AESUtil.encryptAES(result) : result);
                setting.setDescription(description);
                this.saveOrUpdate(setting);
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    @Cacheable
    public <T> T getSettings(Class<T> clazz) {
        try {
            T result = clazz.newInstance();
            for (Field field : clazz.getDeclaredFields()) {
                String value = field.getName();
                boolean aes = false;
                boolean annotationPresent = field.isAnnotationPresent(Mapping.class);
                if (annotationPresent) {
                    Mapping mapping = field.getAnnotation(Mapping.class);
                    value = mapping.value();
                    aes = mapping.aes();
                }
                Settings setting = this.getById(StringUtils.isEmpty(value) ? field.getName() : value);
                if(setting != null){
                    BEAN_UTILS.setProperty(result, field.getName(), aes ? AESUtil.decryptAES(setting.getValue()) : setting.getValue());
                }
            }
            return result;
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

}
